﻿using KinonekoSoftware.CodariaDB.Documents.Theories;
using KinonekoSoftware.CodariaDB.Documents.Theories.Elements;
using KinonekoSoftware.CodariaDB.Runtimes.Initializers;
using KinonekoSoftware.CodariaDB.Utils;
using KinonekoSoftware.Studio.Models.Theories;
using KinonekoSoftware.Studio.Utils.Attributes;

namespace KinonekoSoftware.Studio.Pages.Theories.Elements
{
    public class ElementEditorViewModel : RepositoryGalleryItem
    {
        private readonly        IRepository          _repository;
        private readonly        TheoryEngine_Element _theory;

        private bool _placement;

        public ElementEditorViewModel()
        {
            _repository = Platform.GetRepository();
            _theory     = Platform.GetEngine<TheoryEngine_Element>();

            Elements = new ObservableCollection<TheoryOfElementPresenter>();

            NewElementCommand       = CreateCommand(DoNewElementCommand);
            OpenNotionCommand       = CreateCommand<TheoryOfElementPresenter>(DoOpenNotionCommand);
            OpenStoryCommand        = CreateCommand<TheoryOfElementPresenter>(DoOpenStoryCommand);
            EditElementCommand      = CreateCommand<TheoryOfElementPresenter>(DoEditElementCommand);
            EditTemplatedCommand    = CreateCommand<TheoryOfElementPresenter>(DoEditTemplatedElementCommand);
            RemoveElementCommand    = CreateCommand<TheoryOfElementPresenter>(DoRemoveElementCommand);


            Elements.AddMany(_theory.Collection
                                    .Select(x => TheoryOfElementPresenter.Select(x, Placement)));
        }

        private void Save()
        {
            Xplat.Debug($"正在保存TheoryOfElements，Version:{_theory.Version}");
        }

        //-------------------------------------------------
        //
        //          Command Handlers
        //
        //-------------------------------------------------

        private async void DoNewElementCommand()
        {
            var r = await NewElementViewModel.Create();

            if (!r.IsFinished)
            {
                return;
            }

            var val = r.Value;

            //
            //
            _theory.Add(val);

            //
            //
            Elements.Add(TheoryOfElementPresenter.Select(val, Placement));

            //
            Save();
        }

        private void DoEditTemplatedElementCommand(TheoryOfElementPresenter element)
        {
            if (element is null)
            {
                return;
            }

            var context = new PageContext
            {
                Id = element.Id,
            };
            context.Set(ContextBase.Key_Value, element);
            Core.GoTo<TemplatedElementEditorViewModel>(context);
            //
            Save();
        }

        private async void DoEditElementCommand(TheoryOfElementPresenter element)
        {
            if (element is null)
            {
                return;
            }

            var r = await NewElementViewModel.Edit(element.TargetObject);

            if (!r.IsFinished)
            {
                return;
            }

            //
            //
            Save();

            //
            //
            element.RaiseUpdates();
        }

        private async void DoRemoveElementCommand(TheoryOfElementPresenter element)
        {
            if (element is null)
            {
                return;
            }

            if (!await RemoveItem())
            {
                return;
            }

            Elements.Remove(element);
            _theory.Remove(element.TargetObject);

            //
            //
            Save();
        }

        private void DoOpenNotionCommand(TheoryOfElementPresenter element)
        {
            this.ThisNotion(element.TargetObject);
        }


        private void DoOpenStoryCommand(TheoryOfElementPresenter element)
        {
            this.ThisStory(element.TargetObject);
        }

        //-------------------------------------------------
        //
        //          Properties
        //
        //-------------------------------------------------

        public bool Placement
        {
            get => _placement;
            set
            {
                SetValue(ref _placement, value);
                _theory.ImagePlacement = value;
                Elements.ForEach(x => x.SetPlacement(Placement));
                Save();
            }
        }

        public string TheoryName
        {
            get => _theory.CalledName;
            set
            {
                _theory.CalledName = value;
                RaiseUpdated();
                Save();
            }
        }


        public string CalledName
        {
            get => _theory.CalledName;
            set
            {
                _theory.CalledName = value;
                RaiseUpdated();
                Save();
            }
        }

        public ICommandEX NewElementCommand       { get; }
        public ICommandEX EditElementCommand      { get; }
        public ICommandEX EditTemplatedCommand    { get; }
        public ICommandEX RemoveElementCommand    { get; }
        public ICommandEX OpenNotionCommand       { get; }
        public ICommandEX OpenStoryCommand        { get; }

        public ObservableCollection<TheoryOfElementPresenter> Elements { get; }
    }
}